package com.ssm.opa.common.base.utils;

import com.ssm.opa.common.base.exception.SysException;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * Copyright: Copyright (c) 2016/6/24
 * <p>
 * Company: 途牛科技有限公司华东分公司
 * </p>
 *
 * @author guxudong
 * @version 1.0.0
 * @date 2016/6/24.
 */
public class DateUtil {

	public static final String DEFAULT_DATETIMEFORMAT = "yyyy-MM-dd HH:mm:ss";
	public static final String DEFAULT_DATETIMEFORMAT1 = "yyyy-MM-dd HH:mm:ss.SSS";
	public static final String DEFAULT_DATEFORMAT = "yyyy-MM-dd";
	public static final String DEFAULT_TIMEFORMAT = "HH:mm";
	public static final String DEFAULT_DATEMINFORMAT = "yyyy-MM-dd HH:mm";
	public static final String DEFAULT_DATEHOURFORMAT = "yyyy-MM-dd HH";
	public static final int DAY = 1000 * 3600 * 24;
	public static final long MIN = 1000 * 60;

	public static final String TIMESTAMP_FORMAT_STRING_T = "yyyy-MM-dd'T'HH:mm:ss";

	/**
	 * 将时间格式化指定的格式, 返回String
	 *
	 * @param date
	 * @param format
	 * @return
	 */
	public static String dateFormatToString(Date date, String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(date);
	}

	/**
	 * 将时间格式指定为 yyyy-MM-dd ,返回String
	 *
	 * @param date
	 * @return
	 */
	public static String dateFormatToDateString(Date date) {
		return dateFormatToString(date, DEFAULT_DATEFORMAT);
	}
	
	/**
	 * 将时间格式指定为 yyyy-MM-dd HH:mm ,返回String
	 *
	 * @param date
	 * @return
	 */
	public static String dateFormatToDATEMINFORString(Date date) {
		return dateFormatToString(date, DEFAULT_DATEMINFORMAT);
	}

	/**
	 * 将时间格式指定为 yyyy-MM-dd HH:mm:ss,返回String
	 *
	 * @param date
	 * @return
	 */
	public static String dateFormatToDateTimeString(Date date) {
		return dateFormatToString(date, DEFAULT_DATETIMEFORMAT);
	}

	/**
	 * 将时间格式化指定的格式, 返回Date
	 *
	 * @param date
	 * @param format
	 * @return
	 * @throws ParseException
	 */
	public static Date dateFormatToDate(Date date, String format) throws SysException {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			return sdf.parse(sdf.format(date));
		} catch (ParseException e) {
			throw new SysException(SysException.UNMAPPED_TIME_PATTERN, "日期格式化失败:" + format + "\n" + e.toString());
		}
	}

	/**
	 * 将时间Date  格式化成date类型 yyyy-MM-dd
	 *
	 * @param date
	 * @return
	 * @throws ParseException
	 */
	public static Date dateFormatToDate(Date date) throws SysException {
		SimpleDateFormat sdf = new SimpleDateFormat(DateUtil.DEFAULT_DATEFORMAT);
		try {
			return sdf.parse(sdf.format(date));
		} catch (ParseException e) {
			throw new SysException(SysException.UNMAPPED_TIME_PATTERN, "日期格式化失败:" + DateUtil.DEFAULT_DATEFORMAT + "\n" + e.toString());
		}
	}

	/**
	 * 将yyyy-MM-dd HH:mm:ss 格式字符串转换成时间
	 *
	 * @param dateStr
	 * @return
	 * @throws ParseException
	 */
	public static Date StringFormatToDateTime(String dateStr) throws SysException {
		SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATETIMEFORMAT);
		try {
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			throw new SysException(SysException.UNMAPPED_TIME_PATTERN, "日期格式化失败:" + dateStr + "\n" + e.toString());
		}
	}

	/**
	 * 将String 格式字符串转换成时间
	 *
	 * @param dateStr
	 * @return
	 * @throws ParseException
	 */
	public static Date StringFormatToDate(String dateStr, String format) throws SysException {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		try {
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			throw new SysException(SysException.UNMAPPED_TIME_PATTERN, "日期格式化失败:" + dateStr + "\n" + e.toString());
		}
	}

	/**
	 * 将yyyy-MM-dd 格式字符串转换成时间
	 *
	 * @param dateStr
	 * @return
	 * @throws ParseException
	 */
	public static Date StringFormatToDate(String dateStr) throws SysException {
		SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATEFORMAT);
		try {
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			throw new SysException(SysException.UNMAPPED_TIME_PATTERN, "日期格式化失败:" + dateStr + "\n" + e.toString());
		}
	}

	/**
	 * 两个日期的天数差(不足一天按0天算)
	 *
	 * @param date1
	 * @param date2
	 * @return int
	 */
	public static int dateDiff(Date date1, Date date2) {
		long diff = date1.getTime() - date2.getTime();
		int d = (int) Math.floor((double) Math.abs(diff) / DAY);
		return d > 0 ? d : (0 - d);
	}

	/**
	 * 两个日期的时间比较大小(取日期+时间比较)
	 *
	 * @param date1
	 * @param date2
	 * @return int
	 */
	public static int dateTimeDiff(Date date1, Date date2) {
		long diff = date1.getTime() - date2.getTime();
		return diff > 0 ? 1 : (diff < 0 ? -1 : 0);
	}

	/**
	 * 获取datetime 时间
	 * yyyy-MM-dd HH:mm:ss ---- HH:mm
	 *
	 * @param date
	 * @return int
	 */
	public static String dateTime2Time(Date date) {
		SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_TIMEFORMAT);
		return sdf.format(date);
	}

	/**
	 * 两个日期的分钟数差
	 *
	 * @param date1
	 * @param date2
	 * @return int
	 */
	public static int dateTimeMinus(Date date1, Date date2) {
		long diff = date1.getTime() - date2.getTime();
		int d = (int) Math.floor((double) Math.abs(diff) / MIN);
		return Math.abs(d);
	}

	/**
	 * date 时间计算
	 *
	 * @param date         时间点
	 * @param calendarType 间隔类型(Calendar.*)
	 * @param interval     时间间隔
	 * @return
	 */
	public static Date calculateDate(Date date, int calendarType, int interval) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(calendarType, calendar.get(calendarType) + interval);
		return calendar.getTime();
	}

	/**
	 * 转换时区
	 *
	 * @param sourceDate       源日期
	 * @param sourceTimeZone   源时区，formats: <ul> <li>{@code +hh:mm} <li>{@code -hh:mm} </ul>
	 * @param targetTimeZoneId 目标时区
	 * @return 目标时区的日期
	 */
	public static Date convertToZone(Date sourceDate, String sourceTimeZone, ZoneId targetTimeZoneId) {
		ZoneOffset zoneOffsetSource = ZoneOffset.of(sourceTimeZone);// 源时区
		ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(sourceDate.toInstant(), ZoneId.systemDefault());// 此处zoneOffsetSource无用，后面会重新设置
		// 切换为源时区
		zonedDateTime = zonedDateTime.withZoneSameLocal(zoneOffsetSource);
		// 切换为目标时区
		zonedDateTime = zonedDateTime.withZoneSameInstant(targetTimeZoneId);
		return Date.from(zonedDateTime.toInstant());
	}

	/**
	 * 转为当地北京时间
	 *
	 * @param sourceDate     源日期
	 * @param sourceTimeZone 源时区，formats: <ul> <li>{@code +hh:mm} <li>{@code -hh:mm} </ul>
	 * @return 服务器当地的时间
	 */
	public static Date parseZoneToLocal(Date sourceDate, String sourceTimeZone) {
		String dateStr = dateFormatToString(sourceDate, TIMESTAMP_FORMAT_STRING_T);
		ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateStr + sourceTimeZone, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
		return Date.from(zonedDateTime.toInstant());
	}
	/**
	 * 获取日期为星期几
	 * @param date
	 * @return
	 */
	public static int getDateWeek(Date date){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		Integer[] weeks = {7,1,2,3,4,5,6};
		int week_index = calendar.get(Calendar.DAY_OF_WEEK)-1; 
		
		return weeks[week_index];
	}
}
